#pragma once
#include "IUTSCKernel.hpp"


_NNU_UTSC_BEGIN
    using namespace Base;
    namespace Kernel::Time
    {
        // 辅助结构体存储编码中各时间单位的值
        struct TimeData
        {
            int year;
            int month;
            int day;
            int hour;
            int minute;
            int second;
            int millisecond;
        };

        // 一个 dyadic 节点
        struct DyadicNode {
            uint8_t depth;      // 0..L
            uint16_t path;      // 走过的路径（最多 10bit 足够）
            int lo;             // 节点覆盖的最小值（在 0..(2^L-1) 域）
            int hi;             // 节点覆盖的最大值（同上）
        };

        /// <summary>
        /// UTSC实现类
        /// </summary>
        class UTSCImpl : public IUTSCKernel
        {
        public:
            //初始化
            void init() override;

            //释放
            void release() override;

            /// <summary>
            /// 将时间转化为时间编码（时间点）
            /// </summary>
            /// <param name="time">原始时间</param>
            /// <param name="code">编码结果</param>
            /// <returns></returns>
            bool encode(UTSCTime* time,UTSCElementCode *&code)override;


            /// <summary>
            /// 将时间转化为时间编码（时间范围）
            /// </summary>
            /// <param name="time">开始时间</param>
            /// <param name="end">结束时间</param>
            /// <param name="code">编码结果</param>
            /// <returns></returns>
            bool encode(UTSCTime* start, UTSCTime* end, std::vector<UTSCElementCode>& code)override;


            /// <summary>
            /// 将时间编码转化时间
            /// </summary>
            /// <param name="code">编码时间</param>
            /// <param name="time">解码结果</param>
            bool decode(UTSCElementCode *code, UTSCTime* &time)override;
           

            /// <summary>
            /// 将时间编码转化时间
            /// </summary>
            /// <param name="code">编码时间</param>
            /// <param name="start">解码开始时间结果</param>
            /// <param name="end">解码结束时间结果</param>
            bool decode(std::vector<UTSCElementCode> const& codes, UTSCTime*& start, UTSCTime*& end)override;

            /// <summary>
            /// 对时间点的层级关系查询：Parent层级查询，返回一个时间点；Children层级查询，返回两个时间点；Neighbor层级查询，返回两个时间点
            /// </summary>
            /// <param name="topoType">需要查询的类型</param>
            /// <param name="code">查询对象</param>
            /// <param name="result">查询结果</param>
            /// <param name="size">查询结果中包含的时间点数量</param>
            /// <returns></returns>
            bool structQuery(UTSCStructType topoType,UTSCElementCode *code, UTSCElementCode*&result, int& size)override;


            /// <summary>
            /// 时间拓扑关系查询，共三种情况的查询。一共十三种关系
            /// 1.时间点与时间点之间的拓扑关系查询：A在B之前Before，A在B之后After，相同Equal
            /// 2.时间点与时间片段之间的拓扑关系查询：A在B之前Before，A在B之后After，A与B的起点相同StartWith，A与B的终点相同FinishWith，A在B的中间ContainedBy
            /// 3.时间片段与时间片段之间的拓扑关系查询:
            /// A在B之前Before，A在B之后After，A和B一起开始（A比B短）StartWith，A和B一起开始（A比B长）StartBy，A和B一起结束（A比B短）FinishWith，A和B一起结束（A比B长）FinishBy
            /// A和B相等Equal，A和B相交叉（A比B早），OverlapWith，A和B相交叉（A比B晚）OverlapBy，A包含B Contain，A被B包含ContainedBy，A和B错开（A开始，B结束）MetBy，A和B错开（A结束，B开始）MeetWith
            /// </summary>
            /// <param name="code1">编码1</param>
            /// <param name="code2">编码2</param>
            /// <param name="type">查询对象的类型：type=1：时间点与时间点查询；type=2：时间点与时间片段查询；type=3：时间片段与时间片段查询</param>
            /// <returns></returns>
            UTSCTopoType topoQuery(UTSCElementCode*code1, UTSCElementCode*code2,int type)override;

         
        private:
            // 生成编码信息
            void assignCode(NNU::UTSC::UTSCElementCode*& code, NNU::UTSC::UTSCTime* time, unsigned char tempBase, unsigned char tempLevel, int index);

            // 生成解码信息
            void assignTimeInfo(NNU::UTSC::UTSCTime*& time, int signal, unsigned short data, unsigned char base, int index);

            /*时间范围编解码使用的私有函数*/
            int unitMaxWithPrefix(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& order, const std::vector<int>& prefixVals, int idx);
            void fillLowHigh(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& order, std::vector<int>& sv, std::vector<bool>& sHave, std::vector<int>& ev, std::vector<bool>& eHave);
            void emitUnitRange(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& order, const std::vector<int>& prefix, int idxUnit, int lo, int hi, std::vector<UTSCElementCode>& out);
            bool decodeSingleMinMax(const UTSCElementCode& code, bool minIf, UTSCTime*& outTime);
            void coverDyadicRange(int L, int qlo, int qhi, std::vector<DyadicNode>& out);
            void getNodeRange(int L, uint8_t depth, uint16_t path, int& outLo, int& outHi);
            void getUnitOrder(UTSCTimeSystemType sys, std::vector<UTSCElementType>& order);
            int unitMin(UTSCElementType t);
            void encodeUTCYearPoint(int year, uint16_t& codes, int8_t& signal);
            int decodeUTCYearPoint(uint16_t codes, int8_t signal);
            void putPoint(UTSCElementCode& enc, int idx, UTSCElementType t, int value);
            void putYearPointUTC(UTSCElementCode& enc, int idx, int absYear);
            void putNode(UTSCElementCode& enc, int idx, UTSCElementType t, uint8_t depth, uint16_t path);
            void initCodeFrame(UTSCElementCode& enc);
            int lastSetIndex(const UTSCElementCode& enc);
            void normalizeToOrder(UTSCTime* t, const std::vector<UTSCElementType>& order, std::vector<int>& vals, std::vector<bool>& hasVal);
            bool trySingleNodeEncode(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& cutOrder, const std::vector<int>& sv, const std::vector<int>& ev, std::vector<UTSCElementCode>& out);
            void makeVirtualRanges(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& cutOrder, const std::vector<int>& sv, const std::vector<int>& ev, std::vector<std::pair<std::vector<int>, std::vector<int>>>& out);
            int findLargestDyadic(UTSCTimeSystemType sys, const std::vector<UTSCElementType>& cutOrder, const std::vector<int>& cur, const std::vector<int>& ev);
            int compareTuple(const std::vector<int>& a, const std::vector<int>& b);
            void tailFillToMin(const std::vector<UTSCElementType>& order, std::vector<int>& v, int fromIdx);
            void copyPrefix(const std::vector<int>& src, std::vector<int>& dst, int upto);
            /*--------------*/

            // 检查是否为闰年
            bool isLeapYear(int year);

            // 获取某个月的天数
            int daysInMonth(int year, int month);

            // USTC时间中的值转为TimeData结构
            void USTC2TimeData(UTSCElementCode* code, TimeData& time);

            // 得到TimeData时间点的左或右时间点
            void getSingleNeighborTimeData(TimeData& left, UTSCElementType type, int i);

            // 得到TimeData时间点的左右时间点
            void getNeighborTimeData(TimeData& left, TimeData& right, UTSCElementType type);

            // TimeData中的值赋值给USTC时间编码
            void timeData2UTSC(TimeData& left, TimeData& right, UTSCElementCode*& code, int signal);

            // 得到GEO时间点的左或右时间点
            void adjustGeoTime(std::vector<int>& time, int c);     

            // 时间点和时间点拓扑关系查询
            UTSCTopoType topoQueryPointToPoint(UTSCElementCode* srcCode, UTSCElementCode* tagCode, int iterate);

            // 时间点和时间段拓扑关系查询
            UTSCTopoType topoQueryPointToInterval(UTSCElementCode* srcCode, UTSCElementCode* tagCode_start, UTSCElementCode* tagCode_end);

            // 时间段和时间段关系查询
            UTSCTopoType topoQueryIntervalToInterval(UTSCElementCode* srcCode_start, UTSCElementCode* srcCode_end, UTSCElementCode* tagCode_start, UTSCElementCode* tagCode_end);
        };
    }

_NNU_UTSC_END
